package com.liuyjy.utils.utils;

import org.apache.ibatis.reflection.property.PropertyNamer;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Author liuyjy
 * @Date 2024/12/9 18:16
 * @Description: 通过Function获取字段名
 **/
public class LambdaUtils {


    //默认配置
    static String defaultSplit = "";
    static Integer defaultToType = 0;

    /**
     * 获取实体类的字段名称(实体声明的字段名称)
     */
    public static <T, V> String[] resolve(SFunction<T, ?> ... funcs) {
        if(EmptyUtil.isEmpty(funcs)){
            return new String[0];
        }
        String[] fieldNames = new String[funcs.length];
        for (int i = 0; i < funcs.length; i++) {
            fieldNames[i] = resolve(funcs[i]);
        }
        return fieldNames;
    }
    public static <T, R> String resolve(SFunction<T, R> func) {
        try {
            Method method = func.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(true);
            SerializedLambda lambda = (SerializedLambda) method.invoke(func);
            String methodName = lambda.getImplMethodName();
            return PropertyNamer.methodToProperty(methodName);
        } catch (Exception e) {
            throw new RuntimeException("Lambda解析失败", e);
        }
    }

    private static <T> SerializedLambda getSerializedLambda(SFunction<T, ?> fn) {
        // 从function取出序列化方法
        Method writeReplaceMethod;
        try {
            writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        // 从序列化方法取出序列化的lambda信息
        boolean isAccessible = writeReplaceMethod.isAccessible();
        writeReplaceMethod.setAccessible(true);
        SerializedLambda serializedLambda;
        try {
            serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        writeReplaceMethod.setAccessible(isAccessible);
        return serializedLambda;
    }
}
